public class ThreadDemo3 {
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            for (int i = 0; i < 3; i++) {
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        thread.start();

        // 这时在这里再让主线程等待五秒
        // 因为 thread 线程的执行时间一共是消耗三秒
        try {
            Thread.sleep(5000); // 这个是让主线程先休眠五秒    // 因为 虽然多个线程 之间的执行顺序是有变数的
            // 但是单个线程之内 顺序还是固定的，从上到下打
        } catch (InterruptedException e) {        // 这一段就代表在执行下面join的时候thread就已经结束了，所以main就不会被阻塞了，就直接执行了join
            throw new RuntimeException(e);

        }

        //========^========

        // 所以这里实现执行的是sleep在执行join 之前这一句
        System.out.println("join 之前");

        // 此处的join就是让我们当前的 main 线程来等待 thread 线程执行结束（等待 thread 的 run 执行完）
        try {
            thread.join();  // 此处也需要报一个异常
            // join 一共有三种情况
            // 上面的呢种就是 无参数版本。“死等”不见不散
            // 下面还有两种写法
            // 1. public void join(long millis) // 指定一个超长时间(最大等待时间) // 这种操作方式是很常见的 ~~ 死等容易出问题
            // 2. public void join(long millis,int nanos)
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        System.out.println("join 之后");

        // 本身是执行完start 之后， thread 线程 和 main 线程就并发执行， main 继续往下执行 ， thread 也会继续往下执行
        // 这时main这里 遇到thread.join 的时候就会遇到阻塞（block）
        // 只有一直阻塞到 thread 线程执行结束之后，main 线程才会从join中恢复过来，才能结束往下执行
        // thread 线程肯定比 main 线程先结束


        // 总结就是 ： 如果线程没有结束 join就会继续等待，如果线程已经结束了 此时join就会立即返回
    }
}
